package com.wang.cloudstorage.db.dao;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import com.mongodb.BasicDBObject;
import com.mongodb.util.JSON;
import com.wang.cloudstorage.db.DatabaseClient;

public class INodeDAOImpl extends BaseDAO implements INodeDAO{

	public final static String TABLE_NAME = "acl";
	
	protected String iNodeString;
	
	public INodeDAOImpl(DatabaseClient databaseClient, String iNodeString)
	{
		super(databaseClient);
		this.iNodeString = iNodeString;
	}

	/* (non-Javadoc)
	 * @see com.wang.mongodb.dao.INodeDAO#getACL()
	 */
	public JSONObject getACL() throws JSONException
	{
		BasicDBObject where = new BasicDBObject().append(KEY_INODE, iNodeString);
		List<JSONObject> results = databaseClient.select(where, TABLE_NAME);
		if(!results.isEmpty())
		{
			return results.get(0);
		}
		else
			return null;
	}

	public void deleteACL()
	{
		synchronized(this)
		{
			BasicDBObject where = new BasicDBObject().append(KEY_INODE, iNodeString);
			databaseClient.delete(where, TABLE_NAME);
		}
	}

	public void createACL(String creator)
	{
		BasicDBObject bson = new BasicDBObject().
				append(KEY_INODE, iNodeString).
				append(KEY_CREATOR, creator).
				append(KEY_MANAGER, null).
				append(KEY_VISIBLE, null);
		if(null != creator)
		{
			// When file has been created, grant creator all permissions by default.
			bson.append(KEY_PERMISSION, new BasicDBObject().append(creator , INodeDAO.ACL_ALL_ALLOWED));
		}
		else
		{
			bson.append(KEY_PERMISSION, null);
		}
		
		databaseClient.insert(bson, TABLE_NAME);
	}
	
	public void updateAdministrators(Object administrators)
	{
		synchronized(this)
		{
			BasicDBObject valuesObject = new BasicDBObject();
			valuesObject.append("$set", new BasicDBObject().append(KEY_MANAGER, JSON.parse(administrators.toString())));

			BasicDBObject whereObject = new BasicDBObject().append(KEY_INODE, iNodeString);
			databaseClient.update(valuesObject, whereObject, TABLE_NAME);
		}
	}

	public int getPermission(String userId) throws JSONException
	{
		BasicDBObject selectQuery = new BasicDBObject();
		
		List<BasicDBObject> conditions = new ArrayList<BasicDBObject>();
		conditions.add(new BasicDBObject(KEY_INODE, iNodeString));
		conditions.add(new BasicDBObject(KEY_PERMISSION + "." + userId, new BasicDBObject("$exists", true)));
		selectQuery.put("$and", conditions);

		List<JSONObject> acls = databaseClient.select(selectQuery, TABLE_NAME);
		if(0 == acls.size())
			return 0;
			
		JSONObject acl = acls.get(0);
		JSONObject permissions = (JSONObject) acl.get(KEY_PERMISSION);
		
		return permissions.getInt(userId);

		/*JSONObject acl = this.getACL();
		if(null == acl)
			return INodeDAO.ACL_UNKNOWN;

		Object permissions = acl.get("permissions");
		if(JSONObject.NULL == permissions)
			return INodeDAO.ACL_UNKNOWN;
		
		Object permission = ((JSONObject)permissions).get(userId);
		if(JSONObject.NULL == permission)
			return INodeDAO.ACL_UNKNOWN;
		
		return (Integer) permission;*/
	}
	
	public void createPermission(String permission)
	{
		throw new UnsupportedOperationException();
	}

	public void updatePermission(Object permission) throws JSONException
	{
		synchronized(this)
		{
			BasicDBObject valuesObject = new BasicDBObject();
			valuesObject.append("$set", new BasicDBObject().append(KEY_PERMISSION, JSON.parse(permission.toString())));

			BasicDBObject whereObject = new BasicDBObject().append(KEY_INODE, iNodeString);
			databaseClient.update(valuesObject, whereObject, TABLE_NAME);
		}
	}

	public void deletePermission(String userId) throws JSONException
	{
		synchronized(this)
		{
			JSONObject acl = getACL();
			
			if(null != acl)
			{
				JSONObject permissions = (JSONObject)acl.get(KEY_PERMISSION);
				for(int i=0; i<permissions.length(); i++)
				{
					Object permission = permissions.get(userId);
					if(JSONObject.NULL != permission)
					{
						permissions.remove(userId);
						
						BasicDBObject valuesObject = new BasicDBObject();
						valuesObject.append("$set", new BasicDBObject().append(KEY_PERMISSION, JSON.parse(permissions.toString())));

						BasicDBObject whereObject = new BasicDBObject().append(KEY_INODE, iNodeString);
						
						databaseClient.update(valuesObject,  whereObject, TABLE_NAME);
					}
				}
			}
		}
	}
	
	//
/*	private static JSONArray toArray(List<JSONObject> list)
	{
		final JSONArray ja = new JSONArray();
	    for (final JSONObject obj : list) {
	        ja.put(obj);
	    }
	    
	    return ja;
	}
	
	private static List<JSONObject> toList(final JSONArray ja) {
		final int len = ja.length();
		final ArrayList<JSONObject> result = new ArrayList<JSONObject>(len);
		for (int i = 0; i < len; i++) {
			final JSONObject obj = ja.optJSONObject(i);
			if (obj != null) {
				result.add(obj);
			}
		}
		return result;
	}*/
}
